package tp1.arbolBmas;

import tp1.arbolBmas.nodo.Clave;
import tp1.arbolBmas.nodo.Constantes;
import tp1.arbolBmas.nodo.Hoja;
import tp1.arbolBmas.nodo.Nodo;
import tp1.arbolBmas.nodo.NodoConHijos;
import tp1.arbolBmas.nodo.Raiz;
import tp1.arbolBmas.nodo.dato.DatoHoja;
import Exceptions.CommonException;

public class ArbolBmas implements IOperaciones
{
	private NodoConHijos raiz;
	
	public ArbolBmas()
	{
		raiz = null;
	}
	
	public ArbolBmas(NodoConHijos raiz) {
		super();
		this.raiz = raiz;
	}

	public NodoConHijos getRaiz() {
		return raiz;
	}

	public void setRaiz(NodoConHijos raiz) {
		this.raiz = raiz;
	}

	// Implementacion de los metodos de la interface IOperaciones
	
	 
	public void agregar(Nodo nodo) 
	{
		//verifico si es el primer nodo que se agrega
		if( raiz == null)
		{
			raiz = (Raiz) nodo;
		}
		else
		{
			try
			{
				if( nodo.esMenor( raiz ) )
				{
					//Buscar rama izq
					agregarRecursivo(raiz, raiz.getHijoIzquierdo() , nodo  );
				}
				else
				{
					//si nodo es >= raiz, buscar en rama derecha
					agregarRecursivo(raiz, raiz.getHijoDerecho() , nodo );
				}
			}
			catch(CommonException ex)
			{
				loguearError(ex.getMensaje(),ex);
			}
		}
	}

	private void loguearError(String mensaje, CommonException ex) {
		// TODO Auto-generated method stub
		
	}

	/**
	 * 
	 * @param padreActual - Nodo padre del nodo pasado por parametro 'actual'
	 * @param tipo - Rama elegida (izquierda o derecha)
	 * @param actual - Nodo al cual se lo va a comparar con el parametro 'nodo' 
	 * @param nodo - Nodo a insertar
	 * @throws CommonException 
	 */
	private void agregarRecursivo(Nodo padreActual,Nodo actual, Nodo nodo ) throws CommonException 
	{
		//Verifico que actual no sea null, en tal caso quedara nodo como hijo del parametro padreActual.
		if( actual == null ) // CASO BASE 1
		{
			nodo.setPadre(padreActual);
			
			if( nodo.esHijoIzquierdo() )
			{
				((NodoConHijos) padreActual).setHijoIzquierdo( nodo );
			}
			else if( nodo.esHijoDerecho() )
			{
				((NodoConHijos) padreActual).setHijoDerecho( nodo );
			}
			else
			{	
				throw new CommonException("El parametro 'actual' debe apuntar a un nodo de tipo IZQUIERDO o DERECHO"); 
			}
			
			return;
		}	
		
		//Identifico que tipo es actual, (ya que actual != null)
		if( actual instanceof Hoja )
		{
			Hoja hoja = (Hoja) actual;
			
			//Ver si hay overLoad
			boolean hacerSplit = hoja.agregar( (DatoHoja) nodo.getDato() );
			
			if( hacerSplit )
			{
				//Concateno los terminos hoja + nodo
				String[] terminosSplit = new String[ Constantes.CANT_TERMINOS_POR_HOJA + 1 ];
				
				terminosSplit = hoja.getTerminos();
				
				System.out.print("terminos: "); 
				for (String s : terminosSplit) 
				{
					System.out.print(" " + s);
				}
				
			}
			
		}

		//Ya se que actual NO es una Hoja ----> es un nodo con hijos
		if( nodo.esMenor( actual ) )
		{
			//Buscar rama izqquierda de actual
			agregarRecursivo(actual, ((NodoConHijos) actual).getHijoIzquierdo() , nodo  );
		}
		else
		{
			//Buscar rama derecha de actual
			agregarRecursivo(actual, ((NodoConHijos) actual).getHijoDerecho() , nodo  );
		}
	}
	
	 
	public void eliminar(Nodo nodo) {
		// TODO Auto-generated method stub
		
	}

	 
	public Nodo getHijoDerecho(Nodo nodo) {
		// TODO Auto-generated method stub
		return null;
	}

	 
	public Nodo getHijoIzquierdo(Nodo nodo) {
		// TODO Auto-generated method stub
		return null;
	}

	 
	public Nodo getNodo(Clave clave) 
	{
		return null;
	}

	@Override
	public Nodo getHojaParaInsertar(Nodo nodo) 
	{
		if( nodo.getClave().esMenor( raiz.getClave() ) )
		{
			//Buscar rama izq
			getHojaParaInsertarRecursiva( raiz.getHijoIzquierdo() , nodo );
		}
		else
		{
			//buscar en rama derecha
		}
		
		return null;
	}

	/**
	 * 
	 * @param actual - nodo "raiz" del Sub-arbol elegido
	 * @param nodo - Nodo a insertar
	 */
	private void getHojaParaInsertarRecursiva(Nodo actual, Nodo nodo) 
	{
		if( actual instanceof Hoja )
		{
			if( nodo.esMenor( actual ) )
			{
				
			}
			else
			{
				
			}
		}
		else
		{
			
		}
	}
	
	public String toString()
	{
		return raiz.toString();
	}
}
